
Rem
bbdoc: Bounding box
about: Required Components: THitBoxComponent, TPositionComponent, TTransformComponent, TQuadTreeComponent

end rem
Type TCollisionSystem Extends TEntitySystem

	Field _groupManager:TGroupManager
	Field _tagManager:TTagManager

	Field _hitboxMapper:TComponentMapper
	Field _positionMapper:TComponentMapper
	Field _transformMapper:TComponentMapper
	
	'set by SetQuadTree()
	Field _quadTreeSystem:TQuadTreeSystem
	
	
	'debug info
	Field _entitiesChecked:Int
	Field _entitiesSkipped:Int
	Field _boxHits:Int
	Field _imageHits:Int
	
	
	Method Initialize()
		_groupManager = _world.GetGroupManager()
		_tagManager = _world.GetTagManager()
		
		_hitboxMapper = TComponentMapper.Create(New THitBoxComponent, _world)
		_positionMapper = TComponentMapper.Create(New TPositionComponent, _world)
		_transformMapper = TComponentMapper.Create(New TTransformComponent, _world)
		RegisterComponent(New TTransformComponent)
		RegisterComponent(New THitBoxComponent)
		RegisterComponent(New TPositionComponent)
		RegisterComponent(New TQuadTreeComponent)
	End Method
	
	
	rem
	bbdoc: Returns a bag with true or false on the entity id index.
	about: The bag can therefore contain empty positions.
	Image level collision is the default, but boxOnly parameter can be used to to rect checks only.
	endrem
	Method CollidingWith:TBag(e:TEntity, game:TGame, boxOnly:Int = False)
		If _quadTreeSystem = Null Then RuntimeError("No QuadTree present!")
		
		?Debug
		_entitiesChecked = 0
		_entitiesSkipped = 0
		_boxHits = 0
		_imageHits = 0
		?
		
		'get collision box of passed entity.
		Local r:TRect = _quadTreeSystem.GetEntityRect(e)
		Local bag:TBag = _quadTreeSystem.GetEntities(r)
		
		'no collision with passed entity (self)
		bag.Set(e.GetId(), Null)
		
		'set indexes to null for entities that have the collision = false flag.
		For Local i:Int = 0 To bag.GetSize() - 1
			Local this:TEntity = TEntity(bag.Get(i))
			If Not this Then Continue
			
			_entitiesChecked:+1
			
			Local c:THitBoxComponent = THitBoxComponent(_hitboxMapper.Get(this))
			If c._collision = False
			
				?Debug
				_entitiesSkipped:+1
				?
				
				bag.Set(i, Null)
			EndIf
		Next
		
		?Debug
		For Local i:Int = 0 To bag.GetSize() - 1
			If bag.Get(i) Then _boxHits:+1
		Next
		?
		
		If boxOnly = True Then Return bag
		
		'go to image collision check
		'we will remove entities from the bag that do not contain images
		'and those who do not hit the image of the specified entity.
		'if specified entity has no image then we return an empty bag
	
		'retrieve the renderable for entity
		Local rendersystem:TRenderSystem = game.GetRenderSystem()
'		Local rendersystem:TLayeredRenderSystem = TLayeredRenderSystem(game.GetRenderSystem(0))
		Local renderable1:TRenderable = TRenderable(rendersystem.GetRenderable(e))
		
		If Not renderable1 Then RuntimeError "no renderable"
		Local image1:TImage = renderable1.GetImage()
		If Not image1 Then RuntimeError "no image"

		'get image etc details of entity1
		Local x1:Float = renderable1.GetPosition().GetX()
		Local y1:Float = renderable1.GetPosition().GetY()
		Local frame1:Int = renderable1.GetFrame()
		Local rot1:Float = renderable1.GetTransform().GetRotation()
		Local scalex1:Float = renderable1.GetTransform().GetScaleX()
		Local scaley1:Float = renderable1.GetTransform().GetScaleY()		
		
		Local entity2:TEntity
		Local renderable2:TRenderable
		Local image2:TImage
		Local x2:Float, y2:Float
		Local frame2:Int
		Local rot2:Float
		Local scalex2:Float, scaley2:Float
		Local result:Int
		
		'check all entities in bag for image collision
		For Local index:Int = 0 To bag.GetSize() - 1
			entity2 = TEntity(bag.Get(index))
			If entity2
				renderable2 = TRenderable(rendersystem.GetRenderable(entity2))
				If Not renderable2
					bag.Set(index, Null)
					Continue
				Else
					image2 = renderable2.GetImage()
					If Not image2
						bag.Set(index, Null)
						Continue
					EndIf
				EndIf
				
				x2 = renderable2.GetPosition().GetX()
				y2 = renderable2.GetPosition().GetY()
				frame2 = renderable2.GetFrame()
				rot2 = renderable2.GetTransform().GetRotation()
				scalex2 = renderable2.GetTransform().GetScaleX()
				scaley2 = renderable2.GetTransform().GetScaleY()
		
				result:Int = ImagesCollide2(image1, x1, y1, frame1, rot1, scalex1, scaley1,  ..
									  image2, x2, y2, frame2, rot2, scalex2, scaley2)
				If result
					bag.Set(index, entity2)
					
					?Debug
					_imageHits:+1
					?
					
				Else
					bag.Set(index, Null)
				End If
			End If
		Next
		Return bag
	End Method
	
		
	Method SetQuadTree(q:TQuadTreeSystem)
		_quadTreeSystem = q
	End Method

	
	'this system does not process entities.
	Method CheckProcessing:Int()
		Return False
	End Method
	
	
	'not used.
	Method ProcessEntities(entities:TBag)
	End Method
	
	
	'debug
	Method Render(ypos:Int)
		Local e:TEntity
		Local r:TRect
		
		SetAlpha 0.2
		SetColor 255, 50, 50
		For Local i:Int = 0 To _actives.GetSize() - 1
			e = TEntity(_actives.Get(i))
			r = _quadTreeSystem.GetEntityRect(e)
			DrawRect(r.GetX() , r.GetY(), r.GetWidth(), r.GetHeight())
		Next
		
		TRenderState.Push()
		TRenderstate.Reset()
		SetColor 0, 255, 0
		DrawText("Collisions:", 0, ypos)
		DrawText("Total Entities:" + Self.GetActives().GetSize(), 0, ypos + 10)
		DrawText("Checked:" + _entitiesChecked, 0, ypos + 30)
		DrawText("Skipped:" + _entitiesSkipped, 0, ypos + 40)
		DrawText("Box hits:" + _boxhits + ", Image hits:" + _imageHits, 0, ypos + 50)
		TRenderState.Pop()
	End Method
	

End Type
